//

//bib_menu.c

//

//



#include "project.h"

#include <stdio.h>

#include <string.h>

#include <stdlib.h>





void display_menu()

{
    
    printf("\n\n\t\t=HASH-BIBMANAGER (Efficient Ed.)=\n");
    
    printf("\n");
    
    printf("[1]\t\tExit\n");
    
    printf("[2]\t\tInsert\n");
    
    printf("[3]\t\tDisplay All\n");
    
    printf("[4]\t\tDisplay a Publication\n");
    
    printf("[5]\t\tModify a Publication\n");
    
    printf("[6]\t\tDelete a Publication\n");
    
    printf("[7]\t\tExport to File\n");
    
    printf("[8]\t\tImport from File\n");
    
    printf("[9]\t\tDisplay Sorted Publications (by year)\n\n");
    
    printf("\t\t\tEnter an option: ");
    
}







void display_pub_summary(publication_t *publication)

{
    printf("\t\tDOI:\t%s\n", publication->doi);
    
    printf("\t\tTitle:%s\n", publication->title);
    
    printf("\t\tYear:\t%d\n", publication->year);
    
}





void display_pub(entry_t **hash_table){
    int memory_read;
    int nbytes;
    const char *doi;
    puts("Enter DOI of publication:");
    doi = (char *)malloc(nbytes+1);
    memory_read=getline(&doi, &nbytes, stdin);
    
    publication_t *current;
    current = get_entry(hash_table, doi);
    printf("current publication: %p\n", current);
    
    if (current != NULL) {
        printf("\t\tDOI:\t%s\n", current->doi);
        
        printf("\t\tTitle:\t%s\n", current->title);
        
        printf("\t\tYear:\t%d\n", current->year);
        
        printf("\t\tISBN:\t%s\n", current->isbn);
        
        printf("\t\tSource:\t %s\n", current->source);
        
        printf("\t\tAuthors:\t%s\n", current->authors);
        
        printf("\t\tImpact:\t%f\n", current->impact);
    } else {
        printf("Could not find matching Publication to display.\n");
    }
}





void display_pubs(entry_t **hash_table)

{
    for (int i = 0; i < TABLE_SIZE; i++) {
        printf("Table: %p\n", hash_table[i]);
        if (hash_table[i] != NULL) {
            printf("Table not null\n");
            display_pub_summary(hash_table[i]->publication);
            
            for(entry_t * current = hash_table[i]; current != NULL; current=current->next){
                printf("%s\n", current->key);
                printf("%s\n", current->publication->title);
                display_pub_summary(current->publication);
                
            }
        }
    }
    printf("DONE PRINTING PUBS!\n");
    
}





/*void delete_selected_pub(publication_t *publication)
 
 {
 
 int i;
 
 
 
 printf("\n\n\t\t\t\tEnter a DOI number: ");
 
 //scanf("%d", &i);
 
 if(getint(&i)==-1)
 
 {
 
 printf("ERROR");
 
 }
 
 //getchar();
 
 
 
 // decrement the value because working with 0-based array
 
 i--;
 
 if (i<TABLE_SIZE)
 
 {
 
 struct references *tmp;
 
 
 
 // store the last elment into a temp variable
 
 tmp = entries[SIZE - 1];
 
 
 
 // put the one we want to delete into the last element
 
 entries[SIZE - 1] = entries[i];
 
 
 
 // move the last element to the i-th location
 
 entries[i] = tmp;
 
 
 
 // make the array smaller
 
 SIZE--;
 
 }
 
 }
 
 
 
 */



/*void display_sorted_pubs(entry_t **array)
 
 {
 
 int i, j;
 
 publication_t *tmp;
 
 
 
 // go through the array from 1 to nmemb-1
 
 // here, i is an offset
 
 for (i = 1; i < SIZE; i++)
 
 {
 
 // store element of i position in temp
 
 tmp = array[i];
 
 
 
 // compare all the elements from
 
 // j=i-1 to 0 with the value in tmp
 
 j = i - 1;
 
 while (tmp->year[0] < array[j]->year[0] && j >= 0)
 
 {
 
 // move the hole to the j position
 
 array[j + 1] = array[j];
 
 j--;
 
 }
 
 array[j + 1] = tmp;
 
 }
 
 }
 
 */



int getint(int *theint)

{
    
    int data_read;
    
    int size_int = 10;
    
    
    
    int returni=0;
    
    char *string;
    
    string = (char *)malloc(size_int);
    
    data_read = getline(&string, &size_int, stdin);
    
    char* string2=NULL;
    
    if(data_read>0)
        
    {
        
        (*theint)=strtol(string,&string2,10);
        
    }
    
    if(string==string2)
        
    {
        
        returni= -1;
        
    }
    
    free(string);
    
    return returni;
    
}





/*long int data_read()
 
 {
 
 char *ch = NULL;
 
 size_t len = 0;
 
 int line = getline(&ch, &len, stdin);
 
 char *ptr;
 
 
 
 //printf("my_string is %s dabe.\n",ch);
 
 ch[strlen(ch)-1]='\0';
 
 //printf("my_string is %s dabe. \n",ch);
 
 int in = strtol(ch, &ptr, 10);
 
 //printf("Returned %i",in);
 
 free((void*) ch);
 
 return in;
 
 }*/



int main()

{
    
    unsigned int iSelection;
    
    entry_t * hash_table[TABLE_SIZE] = {NULL};
    
    
    
    while (1)
        
    {
        
        display_menu();
        
        
        
        //iSelection = data_read();
        
        //scanf("%d", &iSelection);
        
        if(getint(&iSelection)==-1)
            
        {
            
            printf("ERROR");
            
        }
        
        printf("%d", iSelection);
        
        
        
        if ( iSelection == 2 )
            
        {
            
            insert_entry(hash_table);
            
        }
        
        // 50 == '2'
        
        else if ( iSelection == 3 )
            
        {
            
            display_pubs(hash_table);
            
        }
        
        else if ( iSelection == 4 )
            
        {
            
            display_pub(hash_table);
            
        }
        
        /* else if ( iSelection == 5 )
         
         {
         
         modify_pub(hash_table);
         
         }
         
         else if ( iSelection == 6 )
         
         {
         
         delete_pub(entries);
         
         }
         
         else if ( iSelection == 7 )
         
         {
         
         export_file(entries);
         
         }
         
         else if ( iSelection == 8 )
         
         {
         
         import_file(entries);
         
         }
         
         else if ( iSelection == 9 )
         
         {
         
         display_sorted_pubs(hash_table);
         
         }*/
        
        else if ( iSelection == 1)
            
            break;
        
    }
    
    
    
    // Option 1 -- cleanup memory before you exit
    
    free_table(hash_table);
    
    return 1;
    
}














#ifndef _Biblio_h

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define _Biblio_h




enum {
    
    DOI_SIZE = 8,
    
    TABLE_SIZE = 10,
    
    ISBN_SIZE = 10,
    
    SOURCE_SIZE = 10,
    
    TITLE_SIZE = 30,
    
    AUTHOR_SIZE = 20
    
};





typedef struct _conference {
    
    char venue[15];
    
} conference_t;



typedef struct _journal {
    
    int volume;
    
    int article;
    
} journal_t;





typedef struct _publication {
    
    char doi[DOI_SIZE];
    
    union {
        
        conference_t conference;
        
        journal_t journal;
        
    } type;
    
    char *title;
    
    char isbn[ISBN_SIZE];
    
    char *source;
    
    char *authors/*[AUTHOR_SIZE]*/;    //TODO Add functionality to enter multiple authors
    
    int year;
    
    float impact;
    
} publication_t;





typedef struct _entry {
    
    const char *key;
    
    publication_t *publication;
    
    struct _entry *next;
    
} entry_t;







//IF PUBLICATION_TYPE CONFERENCE, ADD char venue[10]

//IF PUBLICATION_TYPE JOURNAL, ADD int volume; int number;

void display_pub_summary(publication_t *publication);

int hash_function(const char * key){
    unsigned int hash = 0;
    for (int i = 0; i < DOI_SIZE; i++) {
        hash = 31*hash + key[i];
    }
    
    return hash % TABLE_SIZE;
    
}




char* read_text()
{
    int memory_read;
    int nbytes;
    char *data = NULL;
    memory_read = getline(&data, &nbytes, stdin);
    return data;
}


void insert_entry(entry_t **table){
    
    publication_t new_pub = {.doi = "A9U7h09s", .title = "To Kill A Mockingbird", .isbn = "981245364", .source = "Harvard", .authors = "Scott Fitzgerald", .year = 1986, .impact = 4.3};
    
    entry_t entry;
    entry_t *entryP;
    
    publication_t *pubP = (publication_t*)malloc(sizeof(publication_t));
    pubP = &new_pub;
    /*
     printf("DOI:\n");
     fgets(new_pub.doi, DOI_SIZE, stdin);
     new_pub.doi[strlen(new_pub.doi)-1]='\0';
     
     printf("Title:\n");
     new_pub.title = read_text();
     
     printf("ISBN:\n");
     fgets(new_pub.isbn, ISBN_SIZE, stdin);
     new_pub.isbn[strlen(new_pub.isbn)-1]='\0';
     
     printf("Source:\n");
     new_pub.source = read_text();
     
     printf("Authors:\n");
     //TODO Add functionality to enter multiple authors
     new_pub.authors = read_text();
     
     printf("Year:\n");
     new_pub.year = atoi(read_text());
     
     printf("Impact:\n");
     new_pub.impact = atof(read_text());
     */
    
    display_pub_summary(&new_pub);
    entry.key = new_pub.doi;
    
    entry.publication = &new_pub;
    printf("entry.key: %s\n", entry.key);
    
    int index = hash_function(entry.key);
    printf("INDEX: %i\n", index);
    entryP = &entry;
    printf("entry.publication: %p\n", entry.publication);
    printf("&publication: %p\n", &new_pub);
    if (table[index] == NULL){
        table[index] = entryP;
        entry.next = NULL;
    }
    
    
    if (table[index] != NULL){
        
        entry.next= table[index];
        table[index] = entryP;
        
    }
    
}


publication_t * get_entry(entry_t **table, const char *doi) {
    //TODO optimize the if/else{for{if}} into while{if/else}
    printf("doi entered: %s\n", doi);
    int index = hash_function(doi);
    printf("hash fn: %d\n", index);
    entry_t *current;
    current = table[index];
    
    
    while( current != NULL && strcmp(doi, current->publication->doi) != 0) {
        current = current->next;
    };
    
    if (current == NULL || strcmp(doi, current->publication->doi) != 0) {
        printf("table at index for get_entry: %p\n", current);
        printf("DOI does not exist!\n");
        return NULL;
        
    } else {
        printf("Index of entry:%d\n", index);
        return current->publication;
    }
    
}


void free_table(entry_t **table){
    int i;
    entry_t *current, *temp;
    
    if (table == NULL) return;
    for (i=0; i<TABLE_SIZE;i++){
        current = table[i];
        while (current!=NULL) {
            temp = current;
            current = current->next;
            free(temp->publication);
            free(temp);
        }
    }
    free(table);
}
#endif






















#include <stdio.h>

char* read_text()
{
  char *ch = NULL;
  size_t len = 0;
  getline(&ch, &len, stdin);
  ch[strlen(ch)-1]='\0';
  return ch;
}


void insert_entry(entry_t *table){
    publication_t new_pub;
    entry_t *entry;
    publication_t *pubP;
    
    printf("DOI:\n");
    new_pub.doi = read_text();
    printf("Title:\n");
    new_pub.title = read_text();
    printf("ISBN:\n");
    new_pub.isbn = read_text();
    printf("Source\n");
    new_pub.source = read_text();
    printf("Authors\n");
    new_pub.authors = read_text();
    printf("Year:\n");
    new_pub.year = read_text();
    printf("Impact:\n");
    new_pub.impact=read_text();
    
    pubP = &new_pub;
    
    int index = hash_function(new_pub);
    entry->key = index;
    entry->publication = pubP;
    
    if (table[index] == NULL){
        table[index] = entry;
        entry.next = NULL;
    }
}


entry_t *get_entry(entry_t *table[], char doi){
    int index = hash_function(doi);
    if (table[key] == NULL){
        printf("DOI does not exist!\n");
        return NULL
    }
    else {
        entry_t
        current = table[index];
        for(entry_t *current = &table[index]; current != NULL; current=current->next){
            if (current.publication->doi == doi){
                return current;
            }
        }
        printf("There is no entry for this DOI!\n");
        return NULL
    }
}